package com.qys.training.biz.auth.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qys.training.base.entity.PageEntity;
import com.qys.training.base.enumerate.BizCodeEnum;
import com.qys.training.base.exception.QysException;
import com.qys.training.base.utils.ZipMultiFile;
import com.qys.training.biz.auth.entity.Files;
import com.qys.training.biz.auth.entity.FilesExample;
import com.qys.training.biz.auth.mapper.FilesMapper;
import com.qys.training.biz.auth.service.FileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class FileServiceImpl implements FileService {
    public static final Logger logger = LoggerFactory.getLogger(FileServiceImpl.class);
    @Value("${qys.file.storage.path}")
    private String location;
    @Resource
    private FilesMapper filesMapper;

    @Override
    public void upload(MultipartFile file) {
        String oldName = file.getOriginalFilename();
        String fileName = null;
        if (!StringUtils.isEmpty(oldName)) {
            fileName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        }
        Date date = new Date();
        String savePath = location + File.separator + new SimpleDateFormat("yyyy/MM/dd/").format(date);
        //如果不存在,创建文件夹
        File f = new File(savePath);
        if (!f.exists()) {
            boolean mkdirs = f.mkdirs();
            if (!mkdirs) {
                throw new QysException(BizCodeEnum.MKDIR_ERROR.getCode(), BizCodeEnum.MKDIR_ERROR.getDescription());
            }
        }
        try {
            //获取文件字节数组
            byte[] bytes = file.getBytes();
            //文件上传
            file.transferTo(new File(savePath + File.separator + fileName));
            //存储文件元数据
            Files files = new Files();
            files.setFileName(fileName);
            files.setFileSize(String.valueOf(file.getSize()));
            files.setFilePath(savePath);
            files.setFileMd5(DigestUtils.md5DigestAsHex(bytes));
            files.setCreated(date);
            files.setUpdated(date);
            files.setOriFileName(oldName);
            int insert = filesMapper.insert(files);
            if (insert < 1) {
                throw new QysException(BizCodeEnum.UPLOAD_ERROR.getCode(), BizCodeEnum.UPLOAD_ERROR.getDescription());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void update(Long id, MultipartFile file) {
        FilesExample example = new FilesExample();
        FilesExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(id);
        List<Files> filesList = filesMapper.selectByExample(example);
        if (filesList.size() > 0) {
            Files files = filesList.get(0);
            //删除旧文件
            String filePath = files.getFilePath() + File.separator + files.getFileName();
            File f = new File(filePath);
            boolean delete = f.delete();
            //修改原来的文件
            Files newFile = new Files();
            String oldName = file.getOriginalFilename();
            String fileName = null;
            if (!StringUtils.isEmpty(oldName)) {
                fileName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            }
            newFile.setFileName(fileName);
            newFile.setFileSize(String.valueOf(file.getSize()));
            Date date = new Date();
            String savePath = location + File.separator + new SimpleDateFormat("yyyy/MM/dd/").format(date);
            newFile.setFilePath(savePath);
            try {
                newFile.setFileMd5(DigestUtils.md5DigestAsHex(file.getBytes()));
            } catch (IOException e) {
                e.printStackTrace();
            }
            newFile.setUpdated(date);
            int i = filesMapper.updateByExampleSelective(newFile, example);
            if (i < 1) {
                throw new QysException(BizCodeEnum.UPLOAD_ERROR.getCode(), BizCodeEnum.UPLOAD_ERROR.getDescription());
            }
        } else {
            //TODO 没有查到文件
            throw new QysException(BizCodeEnum.ID_ERROR.getCode(), BizCodeEnum.ID_ERROR.getDescription());
        }


    }

    @Override
    public void download(Long id, HttpServletResponse response) {
        FilesExample example = new FilesExample();
        FilesExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(id);
        List<Files> filesList = filesMapper.selectByExample(example);
        if (filesList.size() > 0) {
            Files files = filesList.get(0);
            String filePath = files.getFilePath() + File.separator + files.getFileName();
            File file = new File(filePath);
            if (file.exists()) {
                response.setContentType("application/force-download");
                response.addHeader("Content-Disposition", "attachment;filename=" + files.getFileName());
                byte[] bytes = new byte[1024];
                try (FileInputStream fis = new FileInputStream(file);
                     BufferedInputStream bis = new BufferedInputStream(fis)
                ) {
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(bytes);
                    while (i != -1) {
                        os.write(bytes, 0, i);
                        i = bis.read(bytes);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            //TODO 没有查到文件
            throw new QysException(BizCodeEnum.ID_ERROR.getCode(), BizCodeEnum.ID_ERROR.getDescription());
        }
    }

    @Override
    public void delete(Long id) {
        FilesExample example = new FilesExample();
        FilesExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(id);
        List<Files> filesList = filesMapper.selectByExample(example);
        if (filesList.size() > 0) {
            Files files = filesList.get(0);
            //删除旧文件
            String filePath = files.getFilePath() + File.separator + files.getFileName();
            File f = new File(filePath);
            boolean delete = f.delete();
            if (!delete) {
                throw new QysException(BizCodeEnum.DELETE_ERROR.getCode(), BizCodeEnum.DELETE_ERROR.getDescription());
            }
            filesMapper.deleteByExample(example);
        } else {
            //TODO 没有查到文件
            throw new QysException(BizCodeEnum.ID_ERROR.getCode(), BizCodeEnum.ID_ERROR.getDescription());
        }
    }

    @Override
    public PageEntity select(String fileName, String minSize, String maxSize, Integer currentPage, Integer pageSize) {
        //逆向工程 条件查询
        FilesExample example = new FilesExample();
        FilesExample.Criteria criteria = example.createCriteria();
        if (!StringUtils.isEmpty(fileName)) {
            criteria.andOriFileNameLike("%" + fileName + "%");
        }
        if (!StringUtils.isEmpty(minSize)) {
            criteria.andFileSizeGreaterThan(minSize);
        }
        if (!StringUtils.isEmpty(maxSize)) {
            criteria.andFileSizeLessThan(maxSize);
        }
        //设置分页条件 pageHelper实现原理在README.md中提及
        PageHelper.startPage(currentPage, pageSize);
        List<Files> filesList = filesMapper.selectByExample(example);
        PageInfo<Files> pageInfo = new PageInfo<>(filesList);
        long total = pageInfo.getTotal();
        return new PageEntity(filesList, total);

    }

    @Override
    public void downloadZip(Long[] ids, HttpServletResponse response) {
        List<File> fileList = new ArrayList<>();
        //查询出文件信息 将文件传入fileList
//        for (Long id : ids) {
        FilesExample example = new FilesExample();
        FilesExample.Criteria criteria = example.createCriteria();
//            criteria.andIdEqualTo(id);
        criteria.andIdIn(Arrays.asList(ids));//这里对循环进行修改，在sql中使用in来完成文件列表的查询
        List<Files> filesList = filesMapper.selectByExample(example);
        if (filesList.size() != 0) {
            Files files = filesList.get(0);
            String filePath = files.getFilePath() + File.separator + files.getFileName();
            fileList.add(new File(filePath));
        }
//        }
        String dateStr = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
        String zipPath = location + File.separator + dateStr + File.separator + UUID.randomUUID().toString() + ".zip";
        ZipMultiFile.zipFiles(fileList, new File(zipPath));
        File file = new File(zipPath);
        if (file.exists()) {
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition", "attachment;filename=" + file.getName());
            byte[] bytes = new byte[1024];
            try (FileInputStream fis = new FileInputStream(file);
                 BufferedInputStream bis = new BufferedInputStream(fis)
            ) {
                OutputStream os = response.getOutputStream();
                int i = bis.read(bytes);
                while (i != -1) {
                    os.write(bytes, 0, i);
                    i = bis.read(bytes);
                }
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
